#pragma once
#ifndef THREAD_H
#define THREAD_H


#include <thread>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <sstream>
//#include <g3log/logmessage.hpp>
//#include <g3log/g3log.hpp>
//#include <g3log/logworker.hpp>
#include "ShareQueue.h"

class Thread
{
public:

    Thread(const std::string& name) : _thread(nullptr),
        _pauseFlag(false),
        _stopFlag(false),
        _state(Stoped) {
        this->name = name;
    }


    Thread(const std::string& name, bool needYield) : _thread(nullptr),
        _pauseFlag(false),
        _stopFlag(false),
        _state(Stoped)
    {
        this->name = name;
        this->needYield = needYield;
    }

    virtual ~Thread();

    enum State
    {
        Stoped,
        Running,
        Paused
    };

   /* void setLogLevel(LEVELS logLevel) {
        this->logLevel = logLevel;
    }*/


    bool canSetup = true;

    State state() const;
    void start();
    void stop();
    void pause();
    void resume();
    void sleep(int& s);
    /*void log(const LEVELS level, const std::string& message0, const std::string& message1 = "",
        const std::string& message2 = "",
        const std::string& message3 = "",
        const std::string& message4 = "",
        const std::string& message5 = "",
        const std::string& message6 = "", const std::string& message7 = "") {
        if (level.value >= this->logLevel.value) {
            if (this->logLevel.value == INFO.value) {
                LOG(INFO) << message0 << message1 << message2 << message3 << message4 << message5 << message6 << message7;
            }
            else if (this->logLevel.value == DEBUG.value) {
                LOG(DEBUG) << message0 << message1 << message2 << message3 << message4 << message5 << message6 << message7;
            }
            else if (this->logLevel.value == WARNING.value) {
                LOG(WARNING) << message0 << message1 << message2 << message3 << message4 << message5 << message6 << message7;
            }
            else if (this->logLevel.value == FATAL.value) {
                LOG(FATAL) << message0 << message1 << message2 << message3 << message4 << message5 << message6 << message7;
            }
        }
    }
    LEVELS logLevel = INFO;*/
    std::string key;
    bool executeHandleBeforePause = false;
    virtual void beforeHandle() = 0;
    void inMessage(std::string message) {
        this->inMessageQ->put(message);
    }
    std::string outMessage() {
        return this->outMessageQ->get(true);
    }
    State _state;
protected:
    virtual void process() = 0;

    //virtual void setup(const std::string& message) = 0;

    virtual void run();

    std::unique_ptr<ShareQueue<std::string>> inMessageQ = std::make_unique<ShareQueue<std::string>>(10);
    std::unique_ptr<ShareQueue<std::string>> outMessageQ = std::make_unique<ShareQueue<std::string>>(10);
private:


private:
    std::unique_ptr<std::thread> _thread;
    //std::thread* _thread;
    std::mutex _mutex;
    std::condition_variable _condition;
    std::atomic_bool _pauseFlag;
    std::atomic_bool _stopFlag;

    bool needYield = false;
    std::string name;
    std::string tid;
};

#endif // THREAD_H

